package com.hutiao.snowhb.common;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.hutiao.snowhb.entities.WeixinAccessToken;
import com.hutiao.snowhb.entities.WeixinUserInfo;
import com.hutiao.snowhb.entities.WeixinUserList;
import com.hutiao.snowhb.resource.ConfigInfo;
import com.hutiao.snowhb.wechat.tools.WeiXinTools;
import com.hutiao.snowhb.wechat.vo.WxCustomText;
import com.hutiao.snowhb.wechat.vo.WxCustomTextMsg;
import com.hutiao.snowhb.wechat.vo.WxSendMsg;

public class WeixinUtil {

	private static Logger logger = Logger.getLogger(WeixinUtil.class);
	
	
	public static String getNewAccessToken() throws Exception {
		
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ConfigInfo.wxAppId+"&secret="+ConfigInfo.wxSecret+"";
		
		MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
        //connectionManager.closeIdleConnections(100);
        connectionManager.getParams().setConnectionTimeout(5000);
        connectionManager.getParams().setSoTimeout(5000);
        HttpClient httpclient = new HttpClient(connectionManager);
        GetMethod get = new GetMethod(url);
        
        int responseCode;
		String res;
		WeixinAccessToken token = new WeixinAccessToken();
		
		int retriedCount = 1;
		int retryCount = 3;
		try {
			for (retriedCount = 1; retriedCount <= retryCount; retriedCount++) {
				
				responseCode = httpclient.executeMethod(get);
				res = get.getResponseBodyAsString();
				
				if (responseCode == 200) {
					JSONObject jsonObject = JSONObject.fromObject(res);
					
					Map<String, Class<?>> clazzMap = new HashMap<String, Class<?>>();
			        clazzMap.put("access_token", String.class);
			        clazzMap.put("expires_in", String.class);
			        clazzMap.put("errcode", String.class);
			        clazzMap.put("errmsg", String.class);
					Map<String, ?> mapBean = (Map) JSONObject.toBean(jsonObject, Map.class, clazzMap);
			        
			        if (mapBean.get("access_token") != null) {
			        	token.setAccessToken(mapBean.get("access_token").toString());
			        }
			        if (mapBean.get("expires_in") != null) {
			        	token.setExpiresIn(Integer.parseInt(mapBean.get("expires_in").toString()));
			        }
			        
			        Set<String> set = mapBean.keySet();
			        Iterator<String> iter = set.iterator();
			        while (iter.hasNext()) {
			            String key = iter.next();
			            //fail(key + ":" + mapBean.get(key).toString());
			            logger.debug(key + ":" + mapBean.get(key).toString());
			        }
			        
			        if (mapBean.get("errcode") != null && mapBean.get("errmsg") != null) {
			        	throw new Exception("errcode:"+mapBean.get("errcode").toString()+",errmsg:"+mapBean.get("errmsg").toString()+"");
			        }
					
					break;
				}
				
				try {
					logger.debug(res);
					logger.info("Sleeping 500 millisecs for next retry.");
					Thread.sleep(500);
				} catch (InterruptedException ignore) {
					// nothing to do
				}
				
			}
		} catch (HttpException e) {
			logger.error("HttpException", e);
		} catch (IOException ioe) {
			logger.error("IOException", ioe);
		} finally {
			get.releaseConnection();
			get = null;
		}
		
		token.setSaveTime(System.currentTimeMillis());
		ConfigInfo.ACCESSTOKEN = token;
		return ConfigInfo.ACCESSTOKEN.getAccessToken();
		
	}
	
	
	public static String getAccessToken() throws Exception {
		
		if (ConfigInfo.wxAccessToken != null && !ConfigInfo.wxAccessToken.equals("")
			 && !ConfigInfo.wxAccessToken.equals("null")) {
		
			// 返回配置文件中的token
			return ConfigInfo.wxAccessToken;
			
		}
		
		
		if (ConfigInfo.ACCESSTOKEN != null) {
			
			long expiresin = ConfigInfo.ACCESSTOKEN.getExpiresIn();
			long savetime = ConfigInfo.ACCESSTOKEN.getSaveTime();
			long now = System.currentTimeMillis();
			
			if ((now - savetime) < ((expiresin-600)*1000)) {
				logger.info("use global weixin accesstoken.");
				return ConfigInfo.ACCESSTOKEN.getAccessToken();
			}
			
		}
		
		return getNewAccessToken();
		
	}
	
	
	public static WeixinUserList getUserList() throws Exception {
		
		String accessToken = WeixinUtil.getAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/user/get";
		String param = "access_token=" + accessToken;
		
		HttpClientUtil client = new HttpClientUtil();
		
		String res = client.get(url, param);
		
		JSONObject jsonObject = JSONObject.fromObject(res);
	    
	    WeixinUserList userList = new WeixinUserList();
	    userList.setTotal(Integer.parseInt(jsonObject.get("total").toString()));
	    userList.setCount(Integer.parseInt(jsonObject.get("count").toString()));
	    userList.setNext_openid(jsonObject.get("next_openid").toString());
	    
	    String openIdList = jsonObject.get("data").toString();
	    JSONObject jsonDataObj  = JSONObject.fromObject(openIdList);
	    JSONArray jsonarray = (JSONArray)(jsonDataObj.get("openid"));
	    List<String> list = new ArrayList<String>();
	    for (int i = 0; i<jsonarray.size(); i++) {
	    	list.add(jsonarray.getString(i));
	    }
	    userList.setOpenid(list);
	    
	    return userList;
	}
	
	
	
	public static WeixinUserInfo getUserInfo(String openId) throws Exception {
		
		String accessToken = WeixinUtil.getAccessToken();
		
		String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+accessToken+"&openid="+openId+"&lang=zh_CN";
		
		MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
        //connectionManager.closeIdleConnections(100);
        connectionManager.getParams().setConnectionTimeout(5000);
        connectionManager.getParams().setSoTimeout(5000);
        HttpClient httpclient = new HttpClient(connectionManager);
        GetMethod get = new GetMethod(url);
        get.getParams().setContentCharset("UTF-8");
        
        int responseCode;
		String res;
		WeixinUserInfo user = new WeixinUserInfo();
		
		int retriedCount = 1;
		int retryCount = 3;
		try {
			for (retriedCount = 1; retriedCount <= retryCount; retriedCount++) {
				
				responseCode = httpclient.executeMethod(get);
				res = get.getResponseBodyAsString();
				
				if (responseCode == 200) {
					JSONObject jsonObject = JSONObject.fromObject(res);
					
					Map<String, Class<?>> clazzMap = new HashMap<String, Class<?>>();
			        clazzMap.put("subscribe", String.class);
			        clazzMap.put("openid", String.class);
			        clazzMap.put("nickname", String.class);
			        clazzMap.put("sex", String.class);
			        clazzMap.put("city", String.class);
			        clazzMap.put("country", String.class);
			        clazzMap.put("province", String.class);
			        clazzMap.put("language", String.class);
			        clazzMap.put("headimgurl", String.class);
			        clazzMap.put("subscribe_time", String.class);
			        clazzMap.put("errcode", String.class);
			        clazzMap.put("errmsg", String.class);
			        Map<String, ?> mapBean = (Map) JSONObject.toBean(jsonObject, Map.class, clazzMap);
			        
			        if (mapBean.get("subscribe") != null) {
			        	user.setSubscribe(Integer.parseInt(mapBean.get("subscribe").toString()));
			        	user.setOpenId(mapBean.get("openid").toString());
			        	user.setNickname(user.getSubscribe()==0 ? null : mapBean.get("nickname").toString());
			        	user.setSex(user.getSubscribe()==0 ? 0 : Integer.parseInt(mapBean.get("sex").toString()));
			        	user.setCity(user.getSubscribe()==0 ? null : mapBean.get("city").toString());
			        	user.setCountry(user.getSubscribe()==0 ? null : mapBean.get("country").toString());;
			        	user.setProvince(user.getSubscribe()==0 ? null : mapBean.get("province").toString());
			        	user.setLanguage(user.getSubscribe()==0 ? null : mapBean.get("language").toString());
			        	user.setHeadimgurl(user.getSubscribe()==0 ? null : mapBean.get("headimgurl").toString());
			        	user.setSubscribe_time(user.getSubscribe()==0 ? 0 : Long.parseLong(mapBean.get("subscribe_time").toString()));
			        }
			        
			        Set<String> set = mapBean.keySet();
			        Iterator<String> iter = set.iterator();
			        while (iter.hasNext()) {
			            String key = iter.next();
			            //fail(key + ":" + mapBean.get(key).toString());
			            logger.debug(key + ":" + mapBean.get(key).toString());
			        }
			        
			        if (mapBean.get("errcode") != null && mapBean.get("errmsg") != null) {
			        	throw new Exception("errcode:"+mapBean.get("errcode").toString()+",errmsg:"+mapBean.get("errmsg").toString()+"");
			        }
					
					break;
				}
				
				try {
					logger.debug(res);
					logger.info("Sleeping 500 millisecs for next retry.");
					Thread.sleep(500);
				} catch (InterruptedException ignore) {
					// nothing to do
				}
				
			}
		} catch (HttpException e) {
			logger.error("HttpException", e);
		} catch (IOException ioe) {
			logger.error("IOException", ioe);
		} finally {
			get.releaseConnection();
			get = null;
		}
		
		if (user.getSubscribe() == 0) {
			user.setHeadimgurl(ConfigInfo.wxHeadImg);
			user.setHeadimgurl64(ConfigInfo.wxHeadImg64);
			user.setNickname("anonym");
		} else {
			// 没有头像滴，设置一个默认头像
			if (user.getHeadimgurl() == null || user.getHeadimgurl().equals("")) {
				user.setHeadimgurl(ConfigInfo.wxHeadImg);
				user.setHeadimgurl64(ConfigInfo.wxHeadImg64);
			}
		}
		
		return user;
	}
	
	
	public static String[] downloadFile(String httpUrl, String mediaId) {
		
		String saveFile = ConfigInfo.hdPhotoFilePath + mediaId + ".jpg";
		InputStream is = null;
		OutputStream os = null;
		String[] ret = null;
		
		try {
			 // 构造URL
		    URL url = new URL(httpUrl);
		    // 打开连接
		    URLConnection con = url.openConnection();
		    // 输入流
		    is = con.getInputStream();
		    // 1K的数据缓冲
		    byte[] bs = new byte[1024];
		    // 读取到的数据长度
		    int len;
		    // 输出的文件流
		    os = new FileOutputStream(saveFile);
		    // 开始读取
		    while ((len = is.read(bs)) != -1) {
		      os.write(bs, 0, len);
		    }
		    
		    // 生成缩略图
	 		String thumbFile = ImageUtil.getThumb(saveFile);
	 		
	 		ret = new String[2];
	 		ret[0] = saveFile;
	 		ret[1] = thumbFile;
		    
		    
		} catch (MalformedURLException e) {
			logger.error("MalformedURLException", e);
			ret = null;
		} catch (IOException e) {
			logger.error("IOException", e);
			ret = null;
		} finally {
			// 完毕，关闭所有链接
		    try {
		    	if (is != null) {
					is.close();
				}
				if (os != null) {
					os.close();
				}
			} catch (IOException e) {
				logger.error("IOException", e);
			}
		}
		
		return ret;
		
	}
	
	
	public static String[] downloadMedia(String mediaId) {
		
		String accessToken = "";
		try {
			accessToken = WeixinUtil.getAccessToken();
		} catch (Exception e) {
			logger.error("Exception", e);
		}
		
		System.out.println(accessToken);
		
		String saveFile = ConfigInfo.hdPhotoFilePath + mediaId + ".jpg";
		String httpUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token="+accessToken+"&media_id="+mediaId+"";
		
		HttpClient client = new HttpClient();
		GetMethod httpGet = new GetMethod(httpUrl);
		
		InputStream is = null;
		OutputStream os = null;
		String[] ret = null;
		
		try {
			client.executeMethod(httpGet);
			String contentType = httpGet.getResponseHeader("Content-Type").getValue();
			
			if (contentType.equals("text/plain")) {
				String res = httpGet.getResponseBodyAsString();
				JSONObject jsonObject = JSONObject.fromObject(res);
				Map<String, Class<?>> clazzMap = new HashMap<String, Class<?>>();
		        clazzMap.put("errcode", String.class);
		        clazzMap.put("errmsg", String.class);
		        Map<String, ?> mapBean = (Map) JSONObject.toBean(jsonObject, Map.class, clazzMap);
		        
		        Set<String> set = mapBean.keySet();
		        Iterator<String> iter = set.iterator();
		        while (iter.hasNext()) {
		            String key = iter.next();
		            logger.debug(key + ":" + mapBean.get(key).toString());
		        }
		        
		        if (mapBean.get("errcode") != null && mapBean.get("errmsg") != null) {
		        	logger.error("errcode:"+mapBean.get("errcode").toString()+",errmsg:"+mapBean.get("errmsg").toString()+"");
		        }
				
			} else {
//				String fileName = StringUtils.substringBetween(httpGet.getResponseHeader("Content-Type").getValue(),"filename=", "\"");
//				int fileLength = Integer.parseInt(httpGet.getResponseHeader("Content-Length").getValue());
				
				is = httpGet.getResponseBodyAsStream();
				os = new FileOutputStream(saveFile);
				int len;
				byte[] bs = new byte[1024];
				
				while ((len = is.read(bs)) != -1) {
					os.write(bs, 0, len);
				}
				
				// 生成缩略图
				String thumbFile = ImageUtil.getThumb(saveFile);
				
				ret = new String[2];
				ret[0] = saveFile;
				ret[1] = thumbFile;
			}
			
			
		} catch (HttpException e) {
			logger.error("HttpException", e);
			ret = null;
		} catch (IOException e) {
			logger.error("IOException", e);
			ret = null;
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (os != null) {
					os.close();
				}
			} catch (IOException e) {
				logger.error("IOException", e);
			}
		}
		
		return ret;
        
	}
	
	

	
	
	public static String createMenu(String strMenu) throws Exception {
		
		String accessToken = WeixinUtil.getAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + accessToken;
		
		HttpClientUtil client = new HttpClientUtil();
		String ret = client.post(url, strMenu);
		return ret;
		
	}
	
	@SuppressWarnings("unused")
	private static String changeEncode(String src) {
		try {
			return new String(src.getBytes("UTF-8"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			return src;
		}
	}
	
	
	public static void sendTextMsgCustom(String openId, String msg) throws Exception {
		
		String accessToken = WeixinUtil.getAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
		
		WxCustomTextMsg textmsg = new WxCustomTextMsg(openId, "text", new WxCustomText(msg));
		
		HttpClientUtil client = new HttpClientUtil();
		client.post(url, textmsg.toJSONString());
		
	}
	
	
	public static void main(String[] args) {
		
		String accessToken = "4rC-ik7TPl2Iy53mgc2aBvvnQpoICytwcUII9C61I2D3dYu2gMbqMOkzt_V8j3JzezNKh8vo-2otl6qTvZLpwiaADt0hTX8gYVcwL3zmb9N5-PAwOwWSrQo3qIe9YYCEQu507V_Nosp3VSagSVkGcg";
		String openId = "onJNQuNDGuVCWTw5iEAumXnYX7lk";
		String content = "雪花提醒您该睡觉了：）";
		
		String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
		
		WxCustomTextMsg textmsg = new WxCustomTextMsg(openId, "text", new WxCustomText(content));
		
		HttpClientUtil client = new HttpClientUtil();
		client.post(url, textmsg.toJSONString());
	}
	
	
	
}
